import numpy as np
from functools import partial
from typing import Union, Tuple, List, Dict
from core.engine.ExpressionParser import ExpressionParser  # 引入全局表达式解析器
from core.engine.LayerManager import DynamicLayerManager, build_shared_fixed
# from core.engine.DictTensor import DictTensor
from core.engine.lazy_load import expand_flexible_mapping
from constants import ALIASES, BASIC_WORD_MAPPING, FLEXIBLE_WORD_MAPPING
from utils.attr_dict import AttrFuncDict

# 全局表达式解析器实例
global_expression_parser = ExpressionParser()
shared_fixed = build_shared_fixed()


class HexagramMatrixOperator:
    """
    卦象矩阵操作类，支持名称到索引的映射和平面运算
    """
    _shared_fixed = shared_fixed

    def __init__(self, gua_dict):
        """初始化，每个实例有独立的动态层（10-31层）"""
        self.label = None
        self.aliases = ALIASES
        self.basic_mapping = BASIC_WORD_MAPPING

        if not isinstance(gua_dict,AttrFuncDict) and isinstance(gua_dict,dict):
            gua_dict = AttrFuncDict(**gua_dict)

        expand_flexible = partial(expand_flexible_mapping, gua_dict=gua_dict)
        self.flexible_mapping = AttrFuncDict(expand_flexible, **FLEXIBLE_WORD_MAPPING)

        self.expression_parser = global_expression_parser  # 使用全局表达式解析器
        self.expression_parser.instance_mappings = self.flexible_mapping
        self.dynamic_layer = DynamicLayerManager(gua_dict)

        # 初始化 mapping 属性


    def set_flexible_mappings(self, key: str, expression: str):
        """设置自定义映射规则"""
        if not isinstance(expression, str):
            raise ValueError("表达式必须是字符串")
        self.flexible_mapping[key] = expression

    def _get_single_index(self, key: str) -> int:
        """获取单个键对应的索引"""
        key = self.aliases.get(key, key)
        if key not in self.basic_mapping:
            key = self.flexible_mapping[key]
        return self.basic_mapping[key]

    def get_plane(self, expression: str) -> np.ndarray:
        """获取平面，支持复杂表达式解析"""
        parsed_expr = self.expression_parser.parse_expression(expression)
        result = self._evaluate_expression(parsed_expr)
        return result

    def _evaluate_expression(self, parsed_expr: List) -> np.ndarray:
        stack = []
        for token in parsed_expr:
            if token == '!':
                a = stack.pop()
                array_not = np.logical_not(a)
                layer = np.where(self.dynamic_layer.tensor.mask, array_not, 0)
                stack.append(layer)
            elif token == '&':
                b = stack.pop()
                a = stack.pop()
                stack.append(np.logical_and(a, b))
            elif token == '|':
                b = stack.pop()
                a = stack.pop()
                stack.append(np.logical_or(a, b))
            else:
                index = self._get_single_index(token)
                stack.append(self._get_single_plane(index))
        return stack[0].astype(np.uint8)

    def _get_single_plane(self, index: int) -> np.ndarray:
        """获取单个索引对应的平面"""
        _start = self.dynamic_layer._start  # 9
        if index < _start:
            return self._shared_fixed[index]
        else:
            return self.dynamic_layer.get_dynamic(index - _start)

    def print_info(self, expression: str):
        """打印查询结果信息"""
        try:
            plane = self.get_plane(expression)
            print(f"\n查询: '{expression}'")
            print("结果平面:")
            print(plane)
        except ValueError as e:
            print(f"错误: {e}")

    def judge(self, expression: str, is_explain=False):
        """检查数组是否全为 0"""
        if is_explain:
            print(f"\n查询: '{expression}'")
        try:
            plane = self.get_plane(expression)
            return np.any(plane)
        except ValueError as e:
            print(f"错误: {e}")


# 使用示例
if __name__ == "__main__":
    from test_cases import gua_dicts
    from core.LiuYao import LiuYaoPlace

    idx = 2
    operator = HexagramMatrixOperator(gua_dicts[idx])
    lyp = LiuYaoPlace(gua_dicts[idx])
    lyp.place(output=True)


    # 测试简单查询
    # operator.print_info("主卦")
    # # operator.print_info("水")
    # # operator.print_info("金")
    # operator.print_info("水|金")
    #
    # # 测试复杂表达式
    # operator.print_info("(金|水)&(木|火)")
    # operator.print_info("主卦&(金|水)")
    operator.print_info("世爻")  # 应支持递归解析 "主卦&(金|水)"
    operator.print_info("空亡")  # 应支持递归解析
    operator.print_info("!空亡")  # 应支持递归解析
    operator.print_info("月和3|日差0")
    # operator.print_info("五爻|三爻")  # 或运算
    # operator.print_info("金&水")  # 与运算
    #
    # # 测试嵌套表达式
    # operator.print_info("((金|水)&木)|火")
    # operator.print_info("(主卦&(金|水))|(变卦&(木|火))")
    #
    # # 测试错误处理
    # operator.print_info("不存在")
    # operator.print_info("金&不存在")
    # operator.print_info("(金|水")
